#ifndef _INEX_OPT_H
#define _INEX_OPT_H
#include <cstring>
#include <string>
#include <stdio.h>
#include "memoryFile.h"

#define FILE_NUM_MAP MAP<int, int>
#define CREATE_FILE CreateFileStruct
#define FILE_ID_STRUCT FileMapStruct
#define INDEX_VALUE_DATA IndexValueDataStruct
#define FILE_MAP MAP<STRING, FILE_ID_STRUCT>
#define FILE_NUM(pos, count) pos / count
#define FILE_POS(pos, size) pos % size
#define INDEX_VALUE_BASE_LEN 50
#define FRIST_POS 0
#define LAST_POS 0
#define HEAD_TAG_STRUCT HeadTagStruct
#define GROUP_HEAD_STRUCT GroupHeadStruct
#define GROUP_HEAD_LEN sizeof(GroupHeadStruct)
#define GROUP_HEAD_VALUE memoryGroupHeadItem
#define INDEX_SETTING "setting.cfg"
#define INDEX_EXT ".idx"
#define FULL_PATH(path, filename) path+"/"+filename
#define CREATE_FILE_THREAD createThread

typedef struct {
	FILE_RET_TYPE max;
	FILE_RET_TYPE min;
	FILE_LEN_TYPE top;
	FILE_LEN_TYPE last;
	int count = 0;
} HeadTagStruct;

typedef struct {
	FILE_LEN_TYPE size;
	FILE_LEN_TYPE position;
	FILE_LEN_TYPE shift;
	HEAD_TAG_STRUCT tag;
} GroupHeadStruct;

typedef struct {
	FILE_NUM_MAP fileIds;
	FILE_LEN_TYPE size;
	int head;
	STRING path;
	bool increment;
	FILE_LEN_TYPE top;
	FILE_LEN_TYPE max;
	FILE_LEN_TYPE min;
} FileMapStruct;

typedef struct {
	unsigned char status;
	FILE_RET_TYPE sfront;
	FILE_RET_TYPE sback;
	FILE_RET_TYPE key_val;
	FILE_RET_TYPE indexStart;
	FILE_RET_TYPE indexEnd;
	FILE_RET_TYPE dataStart;
	FILE_RET_TYPE dataEnd;
	FILE_RET_TYPE pos;
} IndexCollectOptStruct;

typedef struct {
	unsigned char status;
	FILE_RET_TYPE top;
	FILE_RET_TYPE last;
	FILE_RET_TYPE count;
} IndexOptStruct;

typedef struct {
	unsigned int id;
	unsigned int num;
} FileInfoStruct;

typedef struct {
	unsigned char status;
	FILE_RET_TYPE name;
	FILE_RET_TYPE value;
	FILE_RET_TYPE start;
	FILE_RET_TYPE end;
} ValueIndexStruct;

typedef struct {
	unsigned char status;
	FILE_LEN_TYPE name;
	FILE_LEN_TYPE start;
	FILE_LEN_TYPE end;
} IndexValueDataStruct;

typedef struct{
	STRING group;
	int file_id;
} CreateFileStruct;

typedef void(*CREATE_FUNC)(CREATE_FILE*);

class memoryGroupHeadItem:public VOBJECT<char, MEM_FILE_STAT>{
	public:
		memoryGroupHeadItem(char* val, MEM_FILE_STAT* mem_stat):VOBJECT<char, MEM_FILE_STAT>(val, mem_stat){};
		GROUP_HEAD_STRUCT* getGroupHead() { return (GROUP_HEAD_STRUCT*)memoryGroupHeadItem::valueObject::getValue(); };
};

extern "C" int calcFileId(STRING, FILE_LEN_TYPE);
extern "C" char* readNext(int, FILE_LEN_TYPE&);
extern "C" int hasIndexCollect(int, FILE_LEN_TYPE, FILE_LEN_TYPE);
extern "C" CHAR_MEM readAndCreate(STRING, FILE_LEN_TYPE);
extern "C" CHAR_MEM readValue(STRING, FILE_LEN_TYPE);
extern "C" APPEND_ITEM findAndWriteGroup(STRING group, char*);
extern "C" int fileCount(const char*);
extern "C" char* findValueIndex(const char*, FILE_LEN_TYPE, FILE_LEN_TYPE,
		unsigned long long, int);
extern "C" int initData(const char*, const char*, FILE_LEN_TYPE, FILE_LEN_TYPE);
extern "C" void closeGroup(STRING);
extern "C" char* readGroup(const char*, FILE_LEN_TYPE, FILE_LEN_TYPE);
extern "C" void writeGroup(const char*, char*, FILE_LEN_TYPE, FILE_LEN_TYPE);
extern "C" FILE_LEN_TYPE groupTell(const char*);
extern "C" char* findWriteGroup(const char*, char*);
extern "C" char* groupAppend(const char*, char*, FILE_LEN_TYPE);
extern "C" char* appendSplit(const char*, char*, int, FILE_LEN_TYPE);
extern "C" FILE_RET_TYPE appendIndexDataValue(const char*, FILE_LEN_TYPE, char*, FILE_LEN_TYPE, int);
extern "C" char* groupHeadTag(const char*);
extern "C" IndexCollectOptStruct* findCollectNext(STRING, FILE_LEN_TYPE, FILE_LEN_TYPE, FILE_LEN_TYPE, int);
extern "C" char* findCollectNextValue(const char*, FILE_LEN_TYPE, FILE_LEN_TYPE, FILE_LEN_TYPE, int);
extern "C" void close_mem();
extern "C" void groupSeek(const char*, FILE_LEN_TYPE);
extern "C" void printGroup(const char*);
extern "C" void loadGroupFile(const char*, const char*);
extern "C" int deleteGroupData(const char*, FILE_LEN_TYPE);
APPEND_ITEM appendGroup(STRING, char*, FILE_LEN_TYPE, FILE_RET_TYPE);
ValueIndexStruct* findValueIndexKeys(STRING, FILE_LEN_TYPE, FILE_LEN_TYPE, FILE_LEN_TYPE, int);
FILE_ID_STRUCT* findFile(STRING);
APPEND_ITEM appendGroup(STRING, char*, FILE_LEN_TYPE);
MEM_FILE_ITEM readMemoryMap(STRING, FILE_LEN_TYPE);
int createGroupFile(STRING, FILE_LEN_TYPE);
GROUP_HEAD_VALUE readGroupHead(STRING);
GROUP_HEAD_VALUE readGroupHead(int);
FileInfoStruct createBindFileValue(STRING, const char*, FILE_LEN_TYPE, int);
void addCreateFile(STRING, int);
void createFileThread(CREATE_FILE*);
bool innerCreateGroup(STRING, FILE_ID_STRUCT*, int);

class createThread{
	private:
		LOCK read_lock;
		void* run_func;
		QUEUE<CREATE_FILE> create_groups;
		SET<STRING> group_names;
		LIST<THREAD*> trd_list;
		int out_cout = 0;
		bool run_stat = true;

	public:
		createThread(int, void*);
		CREATE_FILE readOne();
		void add(CREATE_FILE);
		void end(STRING);
		void close();
		void run();
};

#endif
